package deep1jvmdvm;


import utils.PrintlnUtils;

/*
    jsp 查看Java进程
    jstat工具
    jstat -gc 进程编号

    jvisualvm.exe工具，在jdk的bin目录里，jdk11或者13一下自带，高版本需要单独下载



    老年代，对于Android art 虚拟机 入场条件 阀值是6，

    年轻代


    GC日志查看 -Xms9m -Xmx9m -XX:+PrintGCDetails   // -Xms9m  -Xmx9m 表示 堆的初始大小 和 总量 9 M

     -XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead.


     VM options
     https://blog.csdn.net/wobushixiaobailian/article/details/99685550
     -Xms512m
     -Xmx1024m
     -XX:PerSize=512M
     XX:MaxPersize=1024M
     -noverify


     IDEA的基本使用：让你的IDEA有飞一般的感觉
     https://blog.csdn.net/fly910905/article/details/77868300


     .

        方法一：选中类名或在当前类任何位置，使用快捷键ctrl+F12 查看类结构
 */
public class VIP3Jvm02 {
    public static void main(String[] args) {
        method1();
    }

    private static void method1() {
        long initTotalMemory = Runtime.getRuntime().totalMemory();
        long maxMemory = Runtime.getRuntime().maxMemory();
        initTotalMemory = initTotalMemory / 1024 / 1024;
        maxMemory = maxMemory / 1024 / 1024;

        PrintlnUtils.println("初始总内存："+initTotalMemory+" M");
        PrintlnUtils.println("最大内存："+maxMemory+" M");
        // 初始总内存：260 M
        //
        //    最大内存：4096 M

//        System.gc(); // 主动调用GC
        /*


            Thread Local Allocation Buffer


            什么是TLAB?
            堆区是线程共享区，任何线程都可以访问堆中共享数据
            由于对象示例的创建很频繁，在并发环境下对重划分内存空间是线程不安全的，如果需要 避免多个线程对于同一地址操作，需要加锁，而加锁则会印象分配速度
            所以JVM默认在堆区中开辟了一块空间，专门服务于每一个线程。他为每个线程分配了一 个私有缓存区域，包含在Eden中，这就是TLAB
            多线程同时分配内存是，使用TLAB可以避免一系列的非线程安全问题
            TLAB会作为内存分配的首选，TLAB总空间只会占用EDEN空间的1%
            一旦对象在TLAB空间分配失败，JVM会尝试使用加锁来保证数据操作的原子性，从而直接 在Eden中分配

             堆是分配对象堆唯一选择

            对象逃逸与代码优化

            在《深入理解JAVA虚拟机》一书中，有一段这样的描述： 随着JIT编译器的发展与逃逸分析技术逐渐成熟，栈上分配、标量替换 优化技术将会导致一些微妙的变化，所有的对象分配到堆上也渐渐地 变得不那么“绝对”了。


            逃逸：
            一个对象的作用域仅限于方法区域内部在使用的情况下，此种状况 加做非逃逸
            一个对象如果被外部其他类调用，或者是作用于属性中，则此种现 象被称之为对象逃逸
            此种行为发生在字节码被编译后JIT对于代码的进一步优化

         */
    }


    /**
     *  产生逃逸
     *
     * @return
     */
    public static StringBuffer methoddEscap(String s1, String s2){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(s1).append(s2);
        return stringBuffer;
    }

    // 代码优化建议使用下面的写法

    /**
     *  未产生逃逸
     *
     * @return
     */
    public static String methoddNoEscap(String s1, String s2){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(s1).append(s2);
        return stringBuffer.toString();
    }
}
